package com.atguigu.juc.date930;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Author: shenhao
 * @CreatTime: 2024/9/30 13:52
 * @Version: 1.0
 * 读写锁
 * 读写锁
 *  *
 *  * 对于同一个资源，我们涉及多线程的操作，有读，有写，交替进行。
 *  * 为了保证读写的数据一致性。
 *  *
 *  * 读 读 可共享
 *  * 读 写 不共享
 *  * 写 写 不共享
 *  * 读的时候希望高并发同时进行，可以共享，可以多个线程同时操作进行中.....
 *  * 写的时候为了保证数据一致性，需要独占排它。
 *  *
 *  *
 *  * 题目：5个线程读，5个线程写入，操作同一个资源
 *  *
 *  *
 *  * 1 不加锁                不可以，写的时候原子性被破坏
 *  * 2 加ReentrantLock锁     写控制了，但是没有并发读，并发性能不好
 *  * 3 加读写锁               规范写入，写唯一，读并发
 *  在当前线程拥有写锁的情况下，获取到读锁，随后释放写锁的过程就是锁降级`。
 *  当作者线程写入完毕,然后第一时间要获取读锁,(在写锁没有释放的时候),就是锁降级,
 */
public class ReadWriteLockDemo {
    // 题目：5个线程读，5个线程写入，操作同一个资源
    public static void main(String[] args) throws InterruptedException {
        myCache myCache = new myCache();
        for (int result = 1; result <= 5; result++) {
            int finalResult = result;
            Thread t1=new Thread(()->{
                myCache.write(finalResult +"", finalResult +"");
            },String.valueOf(result));
            t1.start();
        }

        TimeUnit.SECONDS.sleep(2);
        for (int i = 1; i <= 5; i++) {
            int finalI = i;
            Thread t1=new Thread(()->{
                myCache.read(finalI +"");
            },String.valueOf(i));
            t1.start();
        }
    }
}

class myCache{
    Map<String,String> map = new HashMap<>();
    // 第一个版本 普通锁
    //Lock lock = new ReentrantLock();

    /*public void write(String key,String value){
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"写入数据");
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"写入数据结束");
        } finally {
            lock.unlock();
        }
    }

    public void read(String key){
        lock.lock();// 不写似乎就是读写锁的效果
        try {
            System.out.println(Thread.currentThread().getName()+"开始读取!!!");
            String string = map.get(key);
            System.out.println(Thread.currentThread().getName()+"结束读取,结果为:"+string);
        } finally {
            lock.unlock();
        }
    }*/
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock readLock = lock.readLock();
    private Lock writeLock = lock.writeLock();

    public void write(String key,String value){
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"写入数据");
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"写入数据结束");
        } finally {
            writeLock.unlock();
        }
    }

    public void read(String key){
        readLock.lock();// 不写似乎就是读写锁的效果
        try {
            System.out.println(Thread.currentThread().getName()+"开始读取!!!");
            String string = map.get(key);
            System.out.println(Thread.currentThread().getName()+"结束读取,结果为:"+string);
        } finally {
            readLock.unlock();
        }
    }

}